home *** CD-ROM | disk | FTP | other *** search
- /*
- File: RedAnts.c
-
- Contains: This is a very basic snippet to illustrate how to implement a marquee.
-
- there are two good references that cover this stuff. Macintosh Programming Fundamentals
- by Knaster and Rollin, and Programming QuickDraw by Surovell, Hall and Othmer. Both these
- works are published by addison wesley and both have sample code.
-
- What we do here is track the mouse. Periodically during tracking, and after we finish, we
- animate the selection rectangle. We do this by working on a pattern, gMarqueePattern, shifting
- and rotating each row in the pattern, and setting this as the current pattern to use with the
- call to frame rect.
-
- For added spice we set the foreground color to red, this draws the marquee in the red color.
-
- Written by: Nick Thompson
-
- Copyright: Copyright © 1994-1999 by Apple Computer, Inc., All Rights Reserved.
-
- You may incorporate this Apple sample source code into your program(s) without
- restriction. This Apple sample source code has been provided "AS IS" and the
- responsibility for its operation is yours. You are not permitted to redistribute
- this Apple sample source code as "Apple sample source code" after having made
- changes. If you're going to re-distribute the source, we require that you make
- it clear in the source that the code was descended from Apple sample source
- code, but that you've made changes.
-
- Change History (most recent first):
- 7/8/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1
- 4/21/94 nick added facility to show a pict file and draw the marquee over that
- this allows a demo of how to do the updating in the mouse tracker
- routine.
-
-
- */
-
- #include <QuickDraw.h>
- #include <Palettes.h>
- #include <menus.h>
- #include <PictUtils.h>
- #include <QDOffScreen.h>
- #include <Windows.h>
- #include <Dialogs.h>
- #include <Fonts.h>
- #include <TextEdit.h>
- #include <Menus.h>
- #include <DiskInit.h>
- #include <StandardFile.h>
- #include <Devices.h>
-
-
- #define HiWrd(aLong) (((aLong) >> 16) & 0xFFFF)
- #define LoWrd(aLong) ((aLong) & 0xFFFF)
-
- const RGBColor kRGBBlack = {0, 0, 0};
- const RGBColor kRGBWhite = {0xFFFF, 0xFFFF, 0xFFFF};
-
- const char kEnter = 0x03 ;
- const char kReturn = 0x0D ;
- const char kEscape = 0x1B ;
- const char kPeriod = '.' ;
-
-
- typedef struct {
- WindowRecord theWindow ; // the window
- Rect selRect ; // the current selection rect in the window
- } MyWindow, *MyWindowPtr ;
-
- enum {
- mApple = 128,
- mFile,
- mPalette
- } ;
-
- enum {
- iAbout = 1
- } ;
- enum {
- iOpen = 1,
- iClose,
- iUnused1,
- iQuit = 4
- } ;
-
- enum {
- iUsePictPalette = 1
- } ;
-
- static Point gStaggerPos = {50,50} ;
- static Boolean gUsePictPalette = true ;
- Boolean gQuitFlag = false ; // set to true to quit the application
- Rect gLastRect = { 0, 0, 0, 0 } ; // the last one we drew (used to clean up and for the marquee)
- long gLastAnim ;
-
- // pattern used for the marquee
- // translate this to binary to see it!!
-
- Pattern gMarqueePattern = { 0x1f , // 00011111
- 0x3e , // 00111110
- 0x7c , // 01111100
- 0xf8 , // 11111000
- 0xf1 , // 11110001
- 0xe3 , // 11100011
- 0xc7 , // 11000111
- 0x8f } ; // 10001111
-
-
- const int kTimeToAnimate = 1 ;
-
-
- void main( void ) ;
- void MainEventLoop( void ) ;
- void TrackMouse( Point Anchor, WindowPtr theWindow ) ;
- Rect *CheckRect( Rect *theRect ) ;
- void AnimateMarquee( Rect *theSelectionRect, WindowPtr whichWindow, Boolean mustDraw ) ;
- void InitToolbox( void ) ;
- void HandleKeyPress(EventRecord *event) ;
- void HandleMenuCommand(long menuResult) ;
- PicHandle DoReadPICT( short theRef, OSErr *theErr ) ;
- void AdjustMenus( void ) ;
- OSErr DoCreateWindow( PicHandle thePicture ) ;
- void UpdateWindow( WindowPtr theWindow, Rect *refreshArea ) ;
- pascal Boolean OurFilter(DialogPtr dlg, EventRecord *event, short *itemHit) ;
- void FlashDialogItem(DialogPtr dlg, short itemToFlash);
-
-
- void main( void )
- {
- InitToolbox() ;
-
- MainEventLoop();
- }
-
-
-
- void InitToolbox()
- {
- Handle menuBar = nil;
-
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
- InitCursor();
-
- // initialize application globals
-
- gQuitFlag = false;
-
-
- menuBar = GetNewMBar(128); // Read menus into menu bar, MBAR res id is 128
-
- if ( menuBar == nil )
- ExitToShell(); // if we dont have it then quit - your app
- // needs a dialog here
-
- SetMenuBar(menuBar); // Install menus
- DisposeHandle(menuBar);
-
- AppendResMenu(GetMenuHandle(mApple), 'DRVR'); // Add DA names to Apple menu, ID 128
-
- DrawMenuBar();
- }
-
-
- void MainEventLoop()
- {
- EventRecord event;
- // WindowPtr window;
- short thePart;
- Rect screenRect;
- Point aPoint = {100, 100};
- Rect refreshArea ;
- MyWindowPtr window ;
-
-
- while( !gQuitFlag )
- {
- WaitNextEvent( everyEvent, &event, 0, nil ) ;
- AdjustMenus() ;
-
- switch (event.what) {
-
- default:
- if(( window = (MyWindowPtr)FrontWindow()) != nil ) {
- SetPort((WindowPtr)window) ;
- AnimateMarquee( CheckRect( &(((MyWindowPtr)window)->selRect) ), (WindowPtr)window, false ) ;
- }
- break ;
-
- case mouseDown:
-
- thePart = FindWindow( event.where,((WindowPtr *) &window) );
-
- switch( thePart ) {
- case inMenuBar:
- HandleMenuCommand(MenuSelect(event.where));
- break;
-
- case inDrag:
-
- screenRect = (**GetGrayRgn()).rgnBBox;
- DragWindow( (WindowPtr)window, event.where, &screenRect );
- break ;
-
- case inContent:
-
- if ((WindowPtr)window != FrontWindow())
- SelectWindow( (WindowPtr)window );
- else {
- GlobalToLocal( &event.where ) ;
- TrackMouse( event.where, (WindowPtr)window ) ;
- }
-
- break ;
-
- case inGoAway:
- if (TrackGoAway( (WindowPtr)window, event.where )) {
-
- // lose the GWorld
- DisposeGWorld((GWorldPtr)GetWRefCon((WindowPtr)window)) ;
-
- // lose the window
- DisposeWindow ( (WindowPtr)window );
- }
- break ;
-
- default:
- break ;
- }
- break ;
-
-
- case updateEvt:
-
- window = (MyWindowPtr)event.message;
-
- BeginUpdate( (WindowPtr)window );
-
- refreshArea = ((**(window->theWindow.port.visRgn)).rgnBBox);
-
- UpdateWindow( (WindowPtr)window, &refreshArea ) ;
-
- EndUpdate( (WindowPtr)window );
- break ;
-
- case keyDown:
- case autoKey:
- HandleKeyPress(&event);
- break;
-
- case diskEvt:
- if ( HiWrd(event.message) != noErr )
- (void) DIBadMount(aPoint, event.message);
- break;
-
- case osEvt:
- case activateEvt:
- break;
-
-
- }
- }
- }
-
-
- void HandleKeyPress(EventRecord *event)
- {
- char key;
-
- key = event->message & charCodeMask;
-
- // just check to see if we want to quit...
-
- if ( event->modifiers & cmdKey ) { /* Command key down? */
- HandleMenuCommand(MenuKey(key));
- }
- }
-
-
- void HandleMenuCommand(long menuResult)
- {
- short menuID;
- short menuItem;
- Str255 daName;
- DialogPtr theDialog ;
- short itemHit ;
- SFTypeList myTypes = { 'PICT' } ;
- PicHandle thePicture ;
- OSErr err ;
- short theRef ;
-
- StandardFileReply theSFReply ;
-
- menuID = HiWrd(menuResult);
- menuItem = LoWrd(menuResult);
- switch ( menuID ) {
- case mApple:
- switch ( menuItem ) {
- case iAbout:
- theDialog = GetNewDialog ( 128, nil, (WindowPtr)-1 );
- do {
- ModalDialog ( NewModalFilterProc(OurFilter), &itemHit );
- } while( itemHit != ok ) ;
- DisposeDialog ( theDialog );
- break;
-
- default:
- GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
- (void) OpenDeskAcc(daName);
- break;
- }
- break;
- case mFile:
- switch ( menuItem ) {
- case iOpen:
- // Get the file name to open
- StandardGetFile( nil, 1, myTypes, &theSFReply ) ;
-
- // did the user cancel?
- if(!theSFReply.sfGood)
- break ;
-
- // open the file
- err = FSpOpenDF( &theSFReply.sfFile, fsRdPerm, &theRef ) ;
-
- if( err != noErr )
- break ; // should handle this properly
-
- thePicture = DoReadPICT( theRef, &err ) ;
-
- if( err != noErr )
- break ; // should handle this properly
-
- // display the contents
- err = DoCreateWindow( thePicture ) ;
-
- break ;
-
- case iClose:
- DisposeWindow ( FrontWindow() );
- break ;
- case iQuit:
- gQuitFlag = true;
- break;
- }
- break;
-
- case mPalette:
- switch ( menuItem ) {
- case iUsePictPalette :
- // toggle the check mark and the global boolean
- gUsePictPalette = !gUsePictPalette ;
- CheckItem ( GetMenuHandle ( mPalette ), iUsePictPalette, gUsePictPalette );
- break ;
- }
- break ;
- }
- HiliteMenu(0); // Unhighlight whatever MenuSelect or MenuKey hilited
- }
-
- void FlashDialogItem(DialogPtr dlg, short itemToFlash)
- {
- short iKind;
- Handle iHandle;
- Rect iRect;
- unsigned long ignored;
-
- GetDialogItem(dlg, itemToFlash, &iKind, &iHandle, &iRect);
- HiliteControl((ControlHandle) iHandle, 1);
- Delay(8, &ignored);
- HiliteControl((ControlHandle) iHandle, 0);
- }
-
-
- pascal Boolean OurFilter(DialogPtr dlg, EventRecord *event, short *itemHit)
- {
- short iKind;
- Handle iHandle;
- Rect iRect;
- char key;
- short radius;
-
- switch (event->what) {
-
- case nullEvent:
- break;
-
- case keyDown:
- case autoKey:
- key = event->message & charCodeMask;
- if (event->modifiers & cmdKey) { /* Command key down */
- if (key == kPeriod) {
- *itemHit = ok;
- FlashDialogItem(dlg, *itemHit);
- }
- return true; /* This says we handle ALL command keys */
- } else {
- if ((key == kReturn) || (key == kEnter)) {
- *itemHit = ok;
- FlashDialogItem(dlg, *itemHit);
- return true;
- }
- if (key == kEscape) {
- *itemHit = ok;
- FlashDialogItem(dlg, *itemHit);
- return true;
- }
- }
- return false;
-
- case updateEvt:
- SetPort(dlg);
-
- GetDialogItem(dlg, ok, &iKind, &iHandle, &iRect);
- InsetRect(&iRect, -4, -4);
- radius = (iRect.bottom - iRect.top) / 2;
- if (radius < 16)
- radius = 16;
-
- PenSize(3,3);
- FrameRoundRect(&iRect, radius, radius);
- PenNormal();
-
-
- return false;
-
- default:
- return false;
- }
- return false;
- }
-
-
- void AdjustMenus( void )
- {
- WindowPtr theWindow ;
- theWindow = FrontWindow() ;
- if( theWindow != nil ) {
- EnableItem ( GetMenuHandle ( mFile ), iClose );
- }
- else {
- DisableItem ( GetMenuHandle ( mFile ), iClose );
- }
- // make sure the check marks are correct
- CheckItem ( GetMenuHandle ( mPalette ), iUsePictPalette, gUsePictPalette );
- }
-
- PicHandle DoReadPICT( short theRef, OSErr *theErr )
- {
- long theFileSize ;
- PicHandle thePicture ;
-
- // pict files have a 512 byte header at the front - we dont care about this
- // we can find the size of the pict by subtracting 512 bytes from the length
- // of the file. We then want to resize the handle to that and read the data
- // into the resized handle.
-
- if(( *theErr = GetEOF( theRef, &theFileSize )) != noErr ) {
- FSClose( theRef ) ;
- return nil ;
- }
-
- if(( *theErr = SetFPos( theRef, fsFromStart, 512)) != noErr ) {
- FSClose( theRef ) ;
- return nil ;
- }
-
- theFileSize -= 512 ;
-
- thePicture = (PicHandle)NewHandle( theFileSize ) ;
- if( thePicture == nil ) {
- FSClose( theRef ) ;
- *theErr = MemError() ;
- return nil ; // what ever the mem manager error was
- }
-
- HLock( (Handle)thePicture ) ;
- *theErr = FSRead( theRef, &theFileSize, (Ptr)*thePicture ) ;
- HUnlock( (Handle)thePicture ) ;
-
- if( *theErr != noErr ) {
- FSClose( theRef ) ;
- return nil ;
- }
-
- return thePicture ;
- }
-
- OSErr DoCreateWindow( PicHandle thePicture )
- {
-
- Rect theRect ;
- OSErr theErr ;
- GWorldPtr theNewWorld ;
- CGrafPtr savedPort ;
- GDHandle oldDevice ;
- MyWindowPtr myWindowPtr ;
- Rect selectionRect = {0,0,0,0} ;
-
- PictInfo thePictInfo ;
- PaletteHandle thePictPalette = nil ;
- CTabHandle thePictCTab = nil ;
-
- // make an offscreen environment and image the pict into this
- // Make a window the size of the pict
- // store a reference to the GWorld in the Refcon of the window
- // invalidate the window content area.
-
- theRect.top = (**thePicture).picFrame.top ;
- theRect.left = (**thePicture).picFrame.left ;
- theRect.bottom = (**thePicture).picFrame.bottom ;
- theRect.right = (**thePicture).picFrame.right ;
-
- // to we want to attempt to sample the picture...
- if( gUsePictPalette ) {
-
- // use the picture utilities to get the palette for the window
- theErr = GetPictInfo( thePicture, &thePictInfo, returnColorTable, 256, systemMethod, 0) ;
-
- // set up the palette and color table for later use
- thePictPalette = NewPalette( 256, thePictInfo.theColorTable, pmTolerant, 0x5000 ) ;
- thePictCTab = thePictInfo.theColorTable ;
- }
-
- // we are going to cheat a bit here, I only want to deal with
- // 8 bit images for the purposes of this snippet
- theErr = NewGWorld( &theNewWorld, 8, &theRect, thePictCTab, nil, 0L ) ;
-
- if( theErr != noErr )
- return theErr ;
-
- // save the world
- GetGWorld( &savedPort, &oldDevice ) ;
- SetGWorld( theNewWorld, nil ) ;
-
- // render the image into the offscreen buffer
- DrawPicture( thePicture, &theRect ) ;
-
- SetGWorld( savedPort, oldDevice ) ;
-
- // create the window
- OffsetRect( &theRect, gStaggerPos.h, gStaggerPos.v) ;
- gStaggerPos.h += 16 ;
- gStaggerPos.v += 16 ; // heh - should roll these around, but you wont
- // create more than a couple of windows, will you :-)
-
- myWindowPtr = (MyWindowPtr)NewPtr ( sizeof( MyWindow ) );
-
- myWindowPtr = (MyWindowPtr)NewCWindow( (Ptr)myWindowPtr,
- &theRect,
- "\pplayTime",
- true,
- documentProc,
- (WindowPtr)-1,
- true,
- (long)theNewWorld );
-
- myWindowPtr->selRect = selectionRect ;
-
- // and if we set up the palette earlier assign it to the window
- if( thePictPalette != nil ) {
- SetPalette ( (GrafPtr)myWindowPtr, thePictPalette, true );
- }
-
- // make sure it is visible
- ShowWindow( (GrafPtr)myWindowPtr ) ;
-
- SetGWorld( (CGrafPtr)myWindowPtr, nil ) ;
-
- // invalidate the content region of the window - we don't do any drawing to it here.
- InvalRect ( &theRect );
-
- SetGWorld( savedPort, oldDevice ) ;
- return noErr;
- }
-
-
-
- void UpdateWindow( WindowPtr theWindow, Rect *refreshArea )
- {
- GrafPtr savedPort ;
- Rect copyRect ;
- GWorldPtr theNewWorld ;
- PixMapHandle offPixMap ;
-
- GetPort( &savedPort ) ;
- SetPort( theWindow ) ;
-
- // get the GWorld from the window refcon
- theNewWorld = (GWorldPtr)GetWRefCon ( theWindow );
- offPixMap = GetGWorldPixMap( theNewWorld ) ;
-
- SectRect( refreshArea, &(**offPixMap).bounds, ©Rect ) ;
-
- (void) LockPixels( offPixMap ) ;
- RGBForeColor( &kRGBBlack ) ;
- RGBBackColor( &kRGBWhite ) ;
-
- CopyBits( &((GrafPtr)theNewWorld)->portBits,
- &theWindow->portBits,
- ©Rect,
- ©Rect,
- srcCopy,
- nil ) ;
-
- (void) UnlockPixels( offPixMap ) ;
- SetPort( savedPort ) ;
-
- }
-
- void TrackMouse( Point Anchor, WindowPtr theWindow )
- {
- Rect theSelection = { 0, 0, 0, 0 };
- Point thePoint ;
-
-
- SetPort( theWindow ) ;
-
- // get rid of the (possibly) old selection
- if( !EmptyRect( &(((MyWindowPtr)theWindow)->selRect)) )
- UpdateWindow( theWindow, CheckRect( &(((MyWindowPtr)theWindow)->selRect)) ) ;
-
- while( StillDown () ) {
-
- // remove any old ants that were there before!!
- if( !EmptyRect( &theSelection ))
- UpdateWindow( theWindow, CheckRect(&theSelection) ) ;
-
- GetMouse ( &thePoint );
-
- theSelection.top = Anchor.v ;
- theSelection.left = Anchor.h ;
- theSelection.bottom = thePoint.v ;
- theSelection.right = thePoint.h ;
-
- AnimateMarquee( CheckRect(&theSelection), theWindow, true ) ;
-
- }
- ((MyWindowPtr)theWindow)->selRect = theSelection ;
- }
-
-
- Rect *CheckRect( Rect *theRect )
- {
- short temp;
-
- if (theRect->top > theRect->bottom) // Need to reverse top and bottom?
- {
- temp = theRect->top;
- theRect->top = theRect->bottom;
- theRect->bottom = temp;
- }
-
- if (theRect->left > theRect->right) // Need to reverse left and right?
- {
- temp = theRect->left;
- theRect->left = theRect->right;
- theRect->right = temp;
- }
-
- return theRect; // This makes nested calls easier.
- }
-
-
- void AnimateMarquee( Rect *theSelectionRect, WindowPtr whichWindow, Boolean mustDraw )
- {
- #pragma unused (whichWindow)
- short index ;
- unsigned char lastPart ;
-
- if( mustDraw || TickCount() > gLastAnim + kTimeToAnimate ) {
- if( !EmptyRect ( theSelectionRect ) ) {
-
- // we will have a Red marquee for the selection...
- ForeColor( redColor ) ;
-
- // shuffle the bits in the pattern around
- lastPart = gMarqueePattern.pat[7] ;
-
- for( index = 7; index > 0; --index )
- gMarqueePattern.pat[index] = gMarqueePattern.pat[ index-1 ] ;
-
- gMarqueePattern.pat[0] = lastPart ;
- PenNormal() ;
- PenPat( &gMarqueePattern ) ;
- FrameRect( theSelectionRect ) ;
- gLastAnim = TickCount() ;
-
- // reset the port's color to black
- ForeColor( blackColor ) ;
-
- }
- }
- }